package com.cql.service.business.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.cql.common.config.FoodCircleConfig;
import com.cql.common.constant.RedisConstants;
import com.cql.common.constant.FoodCircleConstant;
import com.cql.common.core.DO.*;
import com.cql.common.core.DTO.RegisterDTO;
import com.cql.common.core.DTO.UserDTO;
import com.cql.common.core.redis.RedisCache;
import com.cql.common.exception.user.AccountRepeatException;
import com.cql.common.exception.user.CaptchaException;
import com.cql.common.exception.user.CaptchaExpireException;
import com.cql.common.exception.user.UserNotExistException;
import com.cql.common.utils.FoodCircleUtils;
import com.cql.common.utils.SecurityUtils;
import com.cql.common.utils.StringUtils;
import com.cql.mapper.*;
import com.cql.service.business.UserService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Date;
import java.util.List;


/**
 * @author cql
 */
@Service("userService")
public class UserServiceImpl extends ServiceImpl<UserMapper, UserDO> implements UserService {

    private final Logger logger = LoggerFactory.getLogger(this.getClass());

    @Autowired
    private UserMapper userMapper;

    @Autowired
    private SysUserRoleMapper userRoleMapper;

    @Autowired
    private SysRoleMapper roleMapper;

    @Autowired
    private RedisCache redisCache;

    @Autowired
    private UserRelationMapper userRelationMapper;

    @Autowired
    private MomentMapper momentMapper;

    @Autowired
    private FoodCircleConfig foodCircleConfig;


    @Override
    public UserDO getUserByAccount(String account) {
        if (StringUtils.isNotEmpty(account)) {
            QueryWrapper<UserDO> wrapper = new QueryWrapper<>();
            wrapper.eq("account", account);
            wrapper.eq("status", 0);
            UserDO userDO = userMapper.selectOne(wrapper);
            return userDO;
        }
        return null;
    }

    /**
     * 校验数据的合法性:
     * 1.账号(10~20位，全数字)             [交给注解]
     * 2.密码(6~20位，数字，字母，基本符号)   [交给注解]
     * 3.角色(食客，厨师，店家)               [交给注解]
     *
     * @param register
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public UserDO insertUser(RegisterDTO register) {
        /**
         * 1.先校验验证码是否正确
         */
        String verifyKey = RedisConstants.CAPTCHA_CODE_KEY + register.getUuid();
        String captcha = redisCache.getCacheObject(verifyKey);
        redisCache.deleteObject(verifyKey);

        if (captcha == null) {
            logger.info("注册用户 {} 验证码过期", register.getAccount());
            throw new CaptchaExpireException();
        }

        if (!register.getCode().equalsIgnoreCase(captcha)) {
            logger.info("注册用户 {} 验证码错误", register.getAccount());
            throw new CaptchaException();
        }

        /**
         * 2.再检验用户账号是否重复
         */
        if (this.getUserByAccount(register.getAccount()) != null) {
            logger.info("注册用户 {} 重复", register.getAccount());
            throw new AccountRepeatException();
        }


        /**
         * 1.密码加密存储
         * 2.默认用户昵称
         * 3.默认用户头像
         * 4.默认经验值
         */
        UserDO userDO = new UserDO();
        //用户账号
        userDO.setAccount(register.getAccount());
        //创建时间
        userDO.setRegisterTime(new Date());
        //加密密码
        userDO.setPassword(SecurityUtils.encryptPassword(register.getPassword()));
        //默认昵称
        userDO.setUsername(FoodCircleUtils.getStringRandom(10));
        //登录时间
        userDO.setLoginDate(new Date());

        //默认头像（根据选择的角色设置默认头像）
        if (FoodCircleConstant.BASE_ROLE_DINER.equals(register.getRole())) {
            userDO.setAvatar(foodCircleConfig.getDefaultDiner());
        }
        if (FoodCircleConstant.BASE_ROLE_CHEF.equals(register.getRole())) {
            userDO.setAvatar(foodCircleConfig.getDefaultChef());
        }
        if (FoodCircleConstant.BASE_ROLE_STORE.equals(register.getRole())) {
            userDO.setAvatar(foodCircleConfig.getDefaultStore());
        }

        //1.新增用户
        userMapper.insert(userDO);

        //2.角色关联
        SysUserRoleDO userRoleDO = new SysUserRoleDO();
        userRoleDO.setUserId(userDO.getUserId());
        userRoleDO.setRoleId(register.getRole());

        userRoleMapper.insert(userRoleDO);

        return userDO;
    }

    @Override
    public UserDTO getUserInfoByAccount(String account) {
        //TODO 未完成
        UserDO user = this.getUserByAccount(account);
        if (user == null) {
            logger.error("{} 已被注销，无法访问", account);
            throw new UserNotExistException();
        }
        UserDTO userDTO = new UserDTO();
        BeanUtils.copyProperties(user, userDTO);

        /**
         * 角色
         */
        List<SysRoleDO> roles = roleMapper.getRoleByAccount(user.getUserId());
        for (SysRoleDO role : roles) {
            Long roleId = role.getRoleId();
            if (roleId.equals(FoodCircleConstant.BASE_ROLE_DINER)
                    || roleId.equals(FoodCircleConstant.BASE_ROLE_CHEF)
                    || roleId.equals(FoodCircleConstant.BASE_ROLE_STORE)) {
                userDTO.setRole(role);
                break;
            }
        }

        /**
         * 等级计算
         */
        int level = FoodCircleUtils.getLevel(user.getExp());
        userDTO.setGrade(level);

        /**
         * 粉丝数
         * 文章数:食客和厨师访问的表不一样
         * 访问数:食客和厨师访问的表不一样
         */

        // 粉丝数
        QueryWrapper<UserRelationDO> wrapper = new QueryWrapper<>();
        wrapper.eq("to_user", user.getUserId());
        wrapper.eq("create_time", 0);
        userDTO.setFanNum(userRelationMapper.selectCount(wrapper));

        //食客的文章数
        if (FoodCircleConstant.BASE_ROLE_DINER.equals(userDTO.getRole().getRoleId())) {
            QueryWrapper<MomentDO> queryWrapper = new QueryWrapper<>();
            queryWrapper.eq("user_id", user.getUserId());
            queryWrapper.eq("status", FoodCircleConstant.PUBLISH_STATUS);
            userDTO.setArticleNum(momentMapper.selectCount(queryWrapper));
        }

        //访问数
        userDTO.setViewNum(0L);

        return userDTO;
    }
}